﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Xml;
using System.Data;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace Shine.Util.Convertor
{
    /// <summary>
    /// 对象转换器
    /// </summary>
    public class ObjectConvertor
    {
        /// <summary>
        /// 获取指定类型中所有的属性信息的数组，顺序由里至外（即由基类到子类）
        /// </summary>
        /// <param name="type">指定的类型</param>
        /// <returns></returns>
        public static FieldInfo[] GetTypeFieldInfoArray(Type type)
        {
            FieldInfo[] fieldInfos;
            List<dynamic> fieldInfoLst = GetTypeFieldInfoList(type);
            if (fieldInfoLst == null || fieldInfoLst.Count == 0) return null;
            fieldInfos = new FieldInfo[fieldInfoLst.Count];
            int i = 0;
            foreach (dynamic fieldInfo in fieldInfoLst)
            {
                fieldInfos[i] = fieldInfo;
                i++;
            }
            return fieldInfos;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static List<dynamic> GetTypeAttributes(Type type)
        {
            List<dynamic> atts = new List<dynamic>();
            List<dynamic> att1 = GetTypeFieldInfoList(type);
            if (att1 != null && att1.Count > 0) atts.AddRange(att1);
            List<dynamic> att2 = GetTypePropertyInfos(type);
            if (att2 != null && att2.Count > 0) atts.AddRange(att2);
            return atts;
        }

        /// <summary>
        /// 获取指定类型中所有的属性信息的链表，顺序由里至外（即由基类到子类）
        /// </summary>
        /// <param name="type">指定的类型</param>
        /// <returns></returns>
        public static List<dynamic> GetTypeFieldInfoList(Type type)
        {
            List<dynamic> fieldInfoLst = new List<dynamic>();
            if (type.BaseType.Name.Equals("Object",StringComparison.CurrentCultureIgnoreCase))
            {
                dynamic[] fieldInfos = type.GetFields();
                if (fieldInfos.GetLength(0) > 0)
                {
                    for (int i = 0; i < fieldInfos.GetLength(0); i++)
                    {
                        if (!Contains(fieldInfoLst, fieldInfos[i])) fieldInfoLst.Add(fieldInfos[i]);
                    }
                }
            }
            else
            {
                Type baseType = type.BaseType;
                if (baseType!=null)
                    fieldInfoLst.AddRange(GetTypeFieldInfoList(baseType));
                dynamic[] fieldInfos = type.GetFields();
                if (fieldInfos.GetLength(0) > 0)
                {
                    for (int i = 0; i < fieldInfos.GetLength(0); i++)
                    {
                        if (!Contains(fieldInfoLst, fieldInfos[i])) fieldInfoLst.Add(fieldInfos[i]);
                    }
                }
            }
            return fieldInfoLst;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static List<dynamic> GetTypePropertyInfos(Type type)
        {
            List<dynamic> fieldInfoLst = new List<dynamic>();
            if (type.BaseType.Name.Equals("Object", StringComparison.CurrentCultureIgnoreCase))
            {
                PropertyInfo[] fieldInfos = type.GetProperties();
                if (fieldInfos.GetLength(0) > 0)
                {
                    for (int i = 0; i < fieldInfos.GetLength(0); i++)
                    {
                        if (!Contains(fieldInfoLst, fieldInfos[i])) fieldInfoLst.Add(fieldInfos[i]);
                    }
                }
            }
            else
            {
                Type baseType = type.BaseType;
                if (baseType != null)
                    fieldInfoLst.AddRange(GetTypePropertyInfos(baseType));
                PropertyInfo[] fieldInfos = type.GetProperties();
                if (fieldInfos.GetLength(0) > 0)
                {
                    for (int i = 0; i < fieldInfos.GetLength(0); i++)
                    {
                        if (!Contains(fieldInfoLst, fieldInfos[i])) fieldInfoLst.Add(fieldInfos[i]);
                    }
                }
            }
            return fieldInfoLst;
        }

        /// <summary>
        /// 判断某个字段是否已经被添加
        /// </summary>
        /// <param name="fieldInfos"></param>
        /// <param name="fieldInfo"></param>
        /// <returns></returns>
        private static bool Contains(List<dynamic> fieldInfos, dynamic fieldInfo)
        {
            if (fieldInfos == null || fieldInfos.Count == 0) return false;
            dynamic f = fieldInfos.FirstOrDefault(t => t.Name.Equals(fieldInfo.Name, StringComparison.CurrentCultureIgnoreCase));
            if (f != null) return true;
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="num"></param>
        /// <param name="round"></param>
        /// <returns></returns>
        public static string ToString(double num, int round)
        {
            string str = Math.Truncate(num).ToString() + ".";
            string tmp = num.ToString();
            if(tmp.Contains("."))
                return str + tmp.Replace(str, "").Trim().PadRight(round, '0');
            else
                return str + "0".PadRight(round, '0');
        }

    }
}
